#include "limiterwidget.h"

#include "dm/dmdef.h"


LimiterWidget::LimiterWidget(const double &maxThreshold, QWidget *parent)
    : QWidget{parent}
{
    setMouseTracking(true);
    setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);

    auto layout = new QGridLayout(this);
    thresholdLabel = new ALabel(tr(LABEL_THRESHOLD), this);
    attackLabel = new ALabel(tr(LABEL_ATTACK), this);
    decayLabel = new ALabel(tr(LABEL_DECAY), this);
    thresholdSpinBox = new ADoubleSpinBox(this);
    attackSpinBox = new ASpinBox(this);
    decaySpinBox = new ASpinBox(this);
    ucs = new DynamicXUCS(DynamicX::Limiter, maxThreshold, this);

    layout->addWidget(thresholdLabel, 0, 0, Qt::AlignHCenter);
    layout->addWidget(attackLabel, 0, 1, Qt::AlignHCenter);
    layout->addWidget(decayLabel, 0, 2, Qt::AlignHCenter);
    layout->addWidget(thresholdSpinBox, 1, 0, Qt::AlignHCenter);
    layout->addWidget(attackSpinBox, 1, 1, Qt::AlignHCenter);
    layout->addWidget(decaySpinBox, 1, 2, Qt::AlignHCenter);
    layout->addWidget(ucs, 2, 0, 1, 4);

    thresholdSpinBox->setDecimals(DYNAMIC_X_THRESHOLD_DECIMAL);
    thresholdSpinBox->setSingleStep(DYNAMIC_X_THRESHOLD_STEP);

    thresholdSpinBox->setRange(DYNAMIC_X_THRESHOLD_MIN, maxThreshold);
    attackSpinBox->setRange(DYNAMIC_X_ATTACK_MIN, DYNAMIC_X_ATTACK_MAX);
    decaySpinBox->setRange(DYNAMIC_X_DECAY_MIN, DYNAMIC_X_DECAY_MAX);

    thresholdSpinBox->setSuffix(tr(LABEL_DECIBEL_UINT));
    attackSpinBox->setSuffix(tr(LABEL_TIME_MS_UNIT));
    decaySpinBox->setSuffix(tr(LABEL_TIME_MS_UNIT));

    connect(thresholdSpinBox, QOverload<double>::of(&ADoubleSpinBox::valueChanged), ucs, &DynamicXUCS::setThreshold);

    connect(ucs, &DynamicXUCS::thresholdChanged, thresholdSpinBox, &ADoubleSpinBox::setValue);

    connect(thresholdSpinBox, QOverload<double>::of(&ADoubleSpinBox::valueChanged), this, &LimiterWidget::valueChanged);
    connect(attackSpinBox, QOverload<int>::of(&ASpinBox::valueChanged), this, &LimiterWidget::valueChanged);
    connect(decaySpinBox, QOverload<int>::of(&ASpinBox::valueChanged), this, &LimiterWidget::valueChanged);

    set(Limiter());
}

Limiter LimiterWidget::getData() const
{
    Limiter data;
    data.threshold = thresholdSpinBox->value();
    data.attack = attackSpinBox->value();
    data.decay = decaySpinBox->value();
    return data;
}

void LimiterWidget::set(const Limiter &data)
{
    blockSignals(true);
    thresholdSpinBox->setValue(data.threshold);
    attackSpinBox->setValue(data.attack);
    decaySpinBox->setValue(data.decay);
    blockSignals(false);
}

void LimiterWidget::valueChanged()
{
    emit stateChanged(getData());
}

